package net.valerijtimakov.homefinances.dao.storages.common.mysql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import net.valerijtimakov.homefinances.dao.storages.common.mysql.query_builders.condition.WhereBuilder;
import net.valerijtimakov.homefinances.dao.storages.finances.mysql.IMySqlProvider;
import net.valerijtimakov.homefinances.domain.common.DataItem;
import net.valerijtimakov.homefinances.domain.common.OperationItem;
import net.valerijtimakov.homefinances.exceptions.AppExceptionWrongState;
import net.valerijtimakov.homefinances.exceptions.AppPersProviderException;
import net.valerijtimakov.homefinances.utils.Utils;

public abstract class OperationItemsStorage extends NamedItemsStorage {
	
	public OperationItemsStorage(IMySqlProvider provider) throws AppExceptionWrongState {
		super(provider);
	}

	protected String addDateFieldName = "add_date";
	protected String cathIdFieldName = "cath_id";
	protected String currencyIdFieldName = "currency_id";
	protected String accountIdFieldName = "account_id";

	@Override
	protected <T extends DataItem> void parse(ResultSet rs, T item) throws SQLException {
		super.parse(rs, item);
		OperationItem cItem = (OperationItem)item;
		cItem.setAddDate(rs.getDate(addDateFieldName));
		cItem.setCathegoriId(rs.getLong(cathIdFieldName));
		cItem.setCurrencyId(rs.getLong(currencyIdFieldName));
		cItem.setAccountId(rs.getLong(accountIdFieldName));
	}
	
	@Override
	protected void initSelect() {
		super.initSelect();
		selectQuery.addField(addDateFieldName);
		selectQuery.addField(cathIdFieldName);
		selectQuery.addField(currencyIdFieldName);
		selectQuery.addField(accountIdFieldName);
	}

	@Override
	protected <T extends DataItem> void addData(T item) {
		super.addData(item);
		OperationItem cItem = (OperationItem)item;
		insertQuery.setFieldValue(addDateFieldName, cItem.getAddDate());
		insertQuery.setFieldValue(cathIdFieldName, cItem.getCathegoriId());
		insertQuery.setFieldValue(currencyIdFieldName, cItem.getCurrencyId());
		insertQuery.setFieldValue(accountIdFieldName, cItem.getAccountId());
	}

	@Override
	protected <T extends DataItem> void setUpdatedFields(T item) {
		super.setUpdatedFields(item);
		OperationItem cItem = (OperationItem)item;
		updateQuery.setFieldValue(addDateFieldName, cItem.getAddDate());
		updateQuery.setFieldValue(cathIdFieldName, cItem.getCathegoriId());
		updateQuery.setFieldValue(currencyIdFieldName, cItem.getCurrencyId());
		updateQuery.setFieldValue(accountIdFieldName, cItem.getAccountId());
	}

	public <T extends OperationItem> Map<Long, T> getAccountOperations(long ... accountId) 
		throws AppPersProviderException, AppExceptionWrongState 
	{
		if (accountId == null || accountId.length == 0) {
			return new HashMap<Long, T>();
		}
		initSelect();
		selectQuery.getWhere().createListCondBuilder(accountIdFieldName, Long.class).importFieldValues(Utils.longArrToRef(accountId));
		return getMap();
	}

	protected interface FiltersAdditor {
		void addFilters(WhereBuilder whereBuilder);
	}

	public <T extends OperationItem> Map<Long, T> filterCosts(long[] accountsIds, long[] cathegoriesIds, long[] currenciesIds, 
		Date addDateFrom, Date addDateTo, String namePattern, FiltersAdditor filtersAdditor) 
			throws AppPersProviderException, AppExceptionWrongState 
	{
		initSelect();
		selectQuery.getWhere().createListCondBuilder(accountIdFieldName, Long.class).importFieldValues(Utils.longArrToRef(accountsIds));
		selectQuery.getWhere().createListCondBuilder(cathIdFieldName, Long.class).importFieldValues(Utils.longArrToRef(cathegoriesIds));
		selectQuery.getWhere().createListCondBuilder(currencyIdFieldName, Long.class).importFieldValues(Utils.longArrToRef(currenciesIds));
		selectQuery.getWhere().addIntervalCondBuilder(addDateFieldName, addDateFrom, addDateTo);
		selectQuery.getWhere().setWhereCond(nameFieldName + " LIKE " + namePattern);
		filtersAdditor.addFilters(selectQuery.getWhere());
		return getMap();
	}
	
}
